package com.atguigu.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.client.ProductFeignClient;
import com.atguigu.constant.MqConst;
import com.atguigu.entity.OrderDetail;
import com.atguigu.entity.OrderInfo;
import com.atguigu.enums.ProcessStatus;
import com.atguigu.mapper.OrderInfoMapper;
import com.atguigu.service.OrderDetailService;
import com.atguigu.service.OrderInfoService;
import com.atguigu.util.HttpClientUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 订单表 订单表 服务实现类
 * </p>
 *
 * @author
 * @since 2022-09-12
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Value("${cancel.order.delay}")
    private Integer cancelOrderDelay;

    //保存订单
    @Override
    public Long saveOrderAndDetail(OrderInfo orderInfo) {
        //商品对外交易号
        String outTradeNo = "atguigu" + System.currentTimeMillis();
        orderInfo.setOutTradeNo(outTradeNo);
        orderInfo.setTradeBody("订单描述");
        orderInfo.setCreateTime(new Date());
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MINUTE, 15);
        orderInfo.setExpireTime(instance.getTime());
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //保存基本信息
        baseMapper.insert(orderInfo);
        //保存详细信息
        Long orderId = orderInfo.getId();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderId);
        }
        orderDetailService.saveBatch(orderDetailList);
        //发送一个延迟消息，超时自动取消订单
        rabbitTemplate.convertAndSend(MqConst.CANCEL_ORDER_EXCHANGE, MqConst.CANCEL_ORDER_ROUTE_KEY, orderId, correlationData -> {
            correlationData.getMessageProperties().setDelay(cancelOrderDelay);
            return correlationData;
            });

        return orderId;
    }

    @Override //生成流水号
    public String generateTradeNo(String userId) {
        String tradeNo = UUID.randomUUID().toString();
        //redis中存放
        String tradeNoKye = "user:" + userId + ":tradeNo";
        redisTemplate.opsForValue().set(tradeNoKye, tradeNo);
        return tradeNo;
    }

    @Override //流水号对比
    public boolean checkTradeNo(String tradeNoUI, String userId) {
        String tradeNoKye = "user:" + userId + ":tradeNo";
        String redisTradeNo = (String) redisTemplate.opsForValue().get(tradeNoKye);
        return tradeNoUI.equals(redisTradeNo);
    }

    @Override //提交订单后还需要删除流水号
    public void deleteTradeNo(String userId) {
        String tradeNoKye = "user:" + userId + ":tradeNo";
        redisTemplate.delete(tradeNoKye);
    }

    @Override //验证商品的库存和价格
    public String checkStockAndPrice(OrderInfo orderInfo) {
        StringBuilder sb = new StringBuilder();
        //拿到用户购买的商品清单
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        if (!CollectionUtils.isEmpty(orderDetailList)) {
            for (OrderDetail orderDetail : orderDetailList) {
                String skuNum = orderDetail.getSkuNum();
                Long skuId = orderDetail.getSkuId();
                //判断库存是否足够  http://localhost:8100/hasStock?skuId=24&num=2
                String url = "http://localhost:8100/hasStock?skuId=" + skuId + "&num=" + skuNum;
                String result = HttpClientUtil.doGet(url);
                //0 没库存 1 有库存
                if ("0".equals(result)) {
                    sb.append(orderDetail.getSkuName() + "库存不足");
                }
                //判断价格是否有变化
                BigDecimal redisTimePrice = productFeignClient.getSkuPrice(skuId);
                BigDecimal orderPrice = orderDetail.getOrderPrice();
                if (redisTimePrice.compareTo(orderPrice) != 0) {
                    sb.append(orderDetail.getSkuName() + "价格有变化，请刷新页面");
                }
            }
        }
        return sb.toString();
    }

    //3.根据订单id查询订单信息
    @Override
    public OrderInfo getOrder(Long orderId) {
        //1.基本订单信息
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        //2.订单详情信息
        if (orderId != null) {
            QueryWrapper<OrderDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("order_id",orderId);
            List<OrderDetail> orderDetailList = orderDetailService.list(wrapper);
            orderInfo.setOrderDetailList(orderDetailList);
        }
        return orderInfo;
    }

    //修改订单状态
    @Override
    public void updateOrderStatus(OrderInfo orderInfo, ProcessStatus status) {
        orderInfo.setProcessStatus(status.name());
        orderInfo.setOrderStatus(status.getOrderStatus().name());
        baseMapper.updateById(orderInfo);
    }

    //通知库存系统减库存
    @Override
    public void sendMsgToWareHouse(OrderInfo orderInfo) {
        //修改订单状态为已通知仓库
        updateOrderStatus(orderInfo,ProcessStatus.NOTIFIED_WARE);
        //把数据组织为一个json数据给仓库
        Map<String, Object> dataMap = assembleWareHouseData(orderInfo);
        String dataJson = JSONObject.toJSONString(dataMap);
        //发消息给仓库系统
        rabbitTemplate.convertAndSend(MqConst.DECREASE_STOCK_EXCHANGE,MqConst.DECREASE_STOCK_ROUTE_KEY,dataJson);

    }

    @Override
    public String splitOrder(Long orderId, String wareHouseIdSkuIdMapJson) {
        //获取原始订单
        OrderInfo parentOrderInfo = getOrder(orderId);
        List<Map> wareHouseIdSkuIdMapJsonList = JSONObject.parseArray(wareHouseIdSkuIdMapJson, Map.class);
        List<Map<String,Object>> assembleWareHouseDataList = new ArrayList<>();
        for (Map wareHouseIdSkuIdMap : wareHouseIdSkuIdMapJsonList) {
            String wartHouseId = (String) wareHouseIdSkuIdMap.get("wartHouseId");
            List<String> skuIdList = (List<String>) wareHouseIdSkuIdMap.get("skuIdList");
            //设置子订单信息并保存
            OrderInfo childOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(parentOrderInfo,childOrderInfo);
            childOrderInfo.setId(null);
            childOrderInfo.setParentOrderId(orderId);
            //设置仓库Id
            childOrderInfo.setWareHouseId(wartHouseId);
            //设置子订单详情
            List<OrderDetail> parentOrderDetailList = parentOrderInfo.getOrderDetailList();
            List<OrderDetail> childOrderDetailList = new ArrayList<>();
            BigDecimal childOrderTotalMoney = new BigDecimal(0);
            for (OrderDetail parentOrderDetail : parentOrderDetailList) {
                for (String skuId : skuIdList) {
                    if (parentOrderDetail.getSkuId()==Long.parseLong(skuId)) {
                        BigDecimal orderPrice = parentOrderDetail.getOrderPrice();
                        String skuNum = parentOrderDetail.getSkuNum();
                        childOrderTotalMoney=childOrderTotalMoney.add(orderPrice.multiply(new BigDecimal(skuNum)));
                        childOrderDetailList.add(parentOrderDetail);
                    }
                }
            }
            childOrderInfo.setOrderDetailList(childOrderDetailList);
            childOrderInfo.setTotalMoney(childOrderTotalMoney);
            //保存子订单及子订单详情
            saveOrderAndDetail(childOrderInfo);
            //生成返回给仓库系统的信息
            Map<String, Object> dataMap = assembleWareHouseData(childOrderInfo);
            assembleWareHouseDataList.add(dataMap);
        }
        //拆单后原始订单状态SPLIT
        updateOrderStatus(parentOrderInfo,ProcessStatus.SPLIT);
        //拆单后返回信息给仓库
        return JSONObject.toJSONString(assembleWareHouseDataList);
    }

    private Map<String, Object> assembleWareHouseData(OrderInfo orderInfo) {
        //构造一个map封装数据
        Map<String, Object> dataMap=new HashMap<>();
        dataMap.put("orderId",orderInfo.getId());
        dataMap.put("consignee", orderInfo.getConsignee());
        dataMap.put("consigneeTel", orderInfo.getConsigneeTel());
        dataMap.put("orderComment", orderInfo.getOrderComment());
        dataMap.put("orderBody", orderInfo.getTradeBody());
        dataMap.put("deliveryAddress", orderInfo.getDeliveryAddress());
        dataMap.put("paymentWay", "2");
        //设置仓库id 拆单必须添加这个参数
        if (!StringUtils.isEmpty(orderInfo.getWareHouseId())){
            dataMap.put("wareId",orderInfo.getWareHouseId());
        }

        //商品详情清单
        List<OrderDetail> details = orderInfo.getOrderDetailList();
        ArrayList<Map<String,Object>> detailMapList = new ArrayList<>();
        for (OrderDetail detail : details) {
            Map<String, Object> detailMap=new HashMap<>();
            detailMap.put("skuId",detail.getSkuId());
            detailMap.put("skuNum",detail.getSkuNum());
            detailMap.put("skuName",detail.getSkuName());
            detailMapList.add(detailMap);
        }
        dataMap.put("details",detailMapList);
        return dataMap;
    }
}









